트랜잭션 정의

트랜잭션의 기념 개념은 더 이상 쪼갤 수 없는 최소 단위의 작업.
commit()하든지 rollback()하든지. 이 밖에도 트랜잭션의 동작방식을 제어할 수 있는 몇가지 조건이 있다.

DefaultTransactionDefinition이 구현하고 있는 TransactionDefinition인터페이스는 트랜잭션의 동작방식에 영향을 줄 수 있는 네 가지 속성을 정의하고 있다.

트랜잭션 전파

트랜잭션의 경계에서 이미 진행중인 트랜잭션이 있을 때 또는 없을 때 어떻게 동작할 것인가를 결정하는 방식을 말한다.

  • PROPAGATION_REQUIRED(default) 진행 중인 트랜잭션이 없으면 새로 시작하고, 이미 시작된 트랜잭션이 있으면 이에 참여한다.

  • PROPAGATION_REQUIRES_NEW 항상 새로운 트랜잭션을 시작한다. 즉, 항상 독립적인 트랜잭션을 보장한다.

  • PROPAGATION_NOT_SUPPORTED 트랜잭션 없이 동작하도록 만든다. 진행 중인 트랜잭션이 있어도 무시한다.

### 격리 수준

DefaultTransactionDefinition의 설정된 격리 수준은 ISOLATION_DEFAULT다. 이는 DataSource에 설정되어 있는 디폴트 격리수준을 그대로 따른다는 것이다.

### 제한시간

DefaultTransactionDefinition의 기본 설정된 제한시간은 없다. PROPOGATION_REQUIREDPROPAGATION_REQUIRES_NEW와 함께 사용해야만 의미가 있다.

### 읽기전용 읽기전용 설정을 할 수 있다.

트랜잭션 정의 수정은 어떻게 해야할까? 기본 DefaultTransactionDefinition를 사용하는 대신, TransactionDefinition오브젝트를 DI 받아서 사용하도록 만들면 된다.
하지만 이렇게 되면 동일 TransactionAdvice를 사용하는 모든 트랜잭션의 속성이 한꺼번에 바뀐다는 문제가 있는데, 원하는 메소드만 선택해서 독자적인 트랜잭션 정의를 적용할 수 있는 방법은 없을까?

## 트랜잭션 인터셉터와 트랜잭션 속성 어드바이스 기능을 확장하면 된다. 메소드 이름 패턴에 따라 다른 트랜잭션 정의가 적용되도록 만드는 것이다.

### TransactionInterceptor 스프링이 제공하는 TransactionInterceptorTransactionAdvice와 크게 다르지 않다.
다만 트랜잭션 정의를 메소드 이름 패턴을 이용해서 다르게 지정할 수 있는 방법을 추가로 제공해 줄 뿐이다.

TransactionInterceptor에는 기본적으로 두 가지 종류의 예외처리 방식이 있다. 런타임 예외가 발생하면 트랜잭션은 롤백된다. 체크 예외를 던지는 경우에는 이것을 예외상황으로 해석하지 않고 일종의 비즈니스 로직에 따른, 의미있는 리턴 방식의 한 가지로 인식해서 트랜잭션을 커밋해버린다.

그런데 이러한 기본 원칙을 따르지 않는 경우가 있을 수 있어서 roobackOn()이라는 속성을 둬서 기본 원칙과 다른 예외처리가 가능하게 해준다.

### 메소드 이름 패턴을 이용한 트랜잭션 속성 지정

Properties타입의 transactionAttributes르포터니는 메소드 패턴과 트랜잭션 속성을 키와 값으로 갖는 컬렉션이다.

메소드 이름이 하나 이상의 패턴과 일치하는 경우, 이름 패턴 중에서 가장 정확히 일치하는 것이 적용된다.

### tx네임스페이스를 이용한 설정 방법 TransactionInterceptor타입의 어드바이스 빈과 TransactionAttribute타입의 속성 정보도 tx 스키마의 전용 태그를 이용해 정의할 수 있다.

<bean>태그로 등록하는 경우에 비해 장점이 많으므로 tx스키마의 태그를 사용해 어드바이스를 등록하도록 권장한다.

## 포인트컷과 트랜잭션 속성의 적용 전략

트랜잭션 부가기능을 적용할 후보 메소드 선정 > 포인트컷 메소드별로 트랜잭션의 적용 방식 > 어드바이스의 트랜잭션 전파 속성

### 포인트컷 표현식과 트랜잭션 속성을 정의할 때 따르면 좋은 몇 가지 전략 - 트랜잭션 포인트컷 표현식은 타입 패턴이나 빈 이름을 이용한다.

  • 공통된 메소드 이름 규칙을 통해 최소한의 트랜잭션 어드바이스 속성을 정의한다.

  • 프록시 방식 AOP는 같은 타깃 오브젝트 내의 메소드 호출할 때는 적용되지 않는다.
    -> 해결 ? 1. 스프링 API를 이용해 프록시 오브젝트에 대한 레퍼런스를 가져온 뒤에 같은 오브젝트의 메소드 호출도 프록시를 이용하도록 강제. 2. 바이트코드를 직접 조작하는 방식의 AOP기술 적용

## 트랜잭션 속성 적용 UserService에 적용해보자.

### 트랜잭션 경계 설정의 일원화
일반적으로 특정 계층의 경계를 트랜잭션 경계와 일치시키는 것이 바람직하다. 서비스 계층을 경계로 잡았다면, 다른 계층이나 모듈에서 DAO에 직접 접근하는 것은 차단해야 한다.

### 서비스 빈에 적용되는 포인트컷 표현식 등록

xml <aop:config> <aop:advisor advice-ref="transactionAdvice" pointcut="bean(*Service)"/> </aop:config>